package com.funong.matrix.core.utils;


import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

@Slf4j
public class DateTimeUtil {
    static String yyyy_MM_dd = "yyyy-MM-dd";
    static String yyyyMMdd = "yyyyMMdd";
    static String yyyyMM = "yyyyMM";
    static String domainFormater = "yyMM";
    static String yyyyMMddCN = "yyyy年MM月dd日";
    static String yyyyMMCN = "yyyy年MM月";
    static String yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss";
    static String yyyyMMddHHmmss = "yyyyMMddHHmmss";
    static String yyyy_MM_dd_00 = "yyyy-MM-dd 00:00:00";
    static String yyyy_MM_dd_24 = "yyyy-MM-dd 23:59:59";


    static String yyyy_MM_dd_a_HH_mm_ss = "yyyy-MM-dd ahh:mm:ss";
    static String yyyyMMdd3 = "yyyy年MM月dd日 HH:mm";
    static String yyyyMMdd4 = "yyyy年MM月dd日 HH时mm分";
    static String yyyyMMdd5 = "yyyy年MM月dd日 HH:mm:ss";
    static String HH_mm = "HH:mm";
    static String yyyy_MM_dd_HH_mm = "yyyy-MM-dd HH:mm";
    static String yyyy_MM_dd_T_HH_mm_ss_SSS = "yyyy-MM-dd'T'HH:mm:ss.SSS";
    static String yyyyMMdd00 = "yyyyMMdd00";
    static String yyyyMMdd11 = "yyyy/MM/dd";
    static String yyyyMM11 = "yyyy/MM";

    public static Timestamp now() {
        return new Timestamp(System.currentTimeMillis());
    }

    //=================================格式化方法===============================

    public static String formatString(String time) {
        Date date = new Date();
        try {
            date = new SimpleDateFormat(yyyy_MM_dd_HH_mm_ss).parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return new SimpleDateFormat(yyyyMMddCN).format(date);
    }

    /**
     * @return
     * @文件路径
     * @定价详情表.交易日
     * @交易日
     */
    public static String formatDateString() {
        return formatDateTime(new Date(), yyyy_MM_dd);
    }

    /**
     * @param date
     * @return
     * @定价详情表.交易日
     */
    public static String formatDateString(Date date) {
        return formatDateTime(date, yyyy_MM_dd);
    }

    /**
     * @param date
     * @return
     * @定价详情表.交易日
     */
    public static String formatDateMMString(Date date) {
        return formatDateTime(date, yyyyMM11);
    }

    public static String formatDateStringCN(Date date) {
        return formatDateTime(date, yyyyMMddCN);
    }

    public static String formatDateStringCN(String dateStr) {
        Date date = parseDateTime(dateStr, yyyy_MM_dd_00);
        return formatDateTime(date, yyyyMMddCN);
    }

    public static String formatDayStringCN(String dateStr) {
        Date date = parseDateTime(dateStr, yyyy_MM_dd);
        return formatDateTime(date, yyyyMMddCN);
    }

    public static String formatDateStringCN(Date deliveryStartTime, Date deliveryEndTime) {
        DateFormat sdf = new SimpleDateFormat(yyyyMMddCN, Locale.CHINA);
        return sdf.format(deliveryStartTime) + "至" + sdf.format(deliveryEndTime);
    }

    public static String formatDateDomainCodeCN(String domainCode) {
        Date date = parseDateTime(domainCode, domainFormater);
        return formatDateTime(date, yyyyMMCN);
    }

    public static String formatDateCN(Date time) {
        return formatDateTime(time, yyyyMMCN);
    }

    public static String formatDateValue() {
        return formatDateTime(new Date(), yyyyMMdd);
    }

    /**
     * @param date
     * @return
     * @点价申请表.最新定价日
     */
    public static String formatDateValue(Date date) {
        return formatDateTime(date, yyyyMMdd);
    }

    public static String formatDate(Object date) {
        SimpleDateFormat sdf = new SimpleDateFormat(yyyy_MM_dd_HH_mm_ss);
        return sdf.format(null == date ? new Date() : date);
    }

    public static String formatDateTimeString() {
        return formatDateTime(new Date(), yyyy_MM_dd_HH_mm_ss);
    }

    /**
     * 点价截止日期
     *
     * @param date
     * @return
     */
    public static String formatDateTimeString(Date date) {
        return formatDateTime(date, yyyy_MM_dd_HH_mm_ss);
    }

    public static String formatDateTimeString00(Date date) {
        return formatDateTime(date, yyyy_MM_dd_00);
    }

    public static String formatDateTimeString24(Date date) {
        return formatDateTime(date, yyyy_MM_dd_24);
    }

    public static String formatDateTimeValue() {
        return formatDateTime(new Date(), yyyyMMddHHmmss);
    }

    public static String formatDateTimeValue(Date date) {
        return formatDateTime(date, yyyyMMddHHmmss);
    }


    //=================================转日期方法===============================

    public static Timestamp parseTimeStamp(String t) {
        return parseTimeStamp(t, yyyy_MM_dd_HH_mm_ss);
    }

    public static Timestamp parseTimeStamp(String s, boolean isStandard) {
        //兼容非标字符串，左右空格
        //2019-01-01
        //2019/01/01
        //2019-01-01T16:00:00.000Z
        //2019-01-01 16:00:00
        if (null == s || "".equals(s.trim())) {
            return new Timestamp(System.currentTimeMillis());
        }
        s = s.trim();
        if (!isStandard) {
            if (s.contains("/")) {
                s = s.replaceAll("/", "-");
            }
            //2019-08-21T16:00:00.000Z
            if (s.contains("T")) {
                s = s.replaceAll("T", " ");
            }
            if (s.length() > 19) {
                s = s.substring(0, 18);
            }
            if (s.length() == 10) {
                s = s.trim() + " 00:00:00";
            }
        }
        return parseTimeStamp(s, yyyy_MM_dd_HH_mm_ss);
    }

    //查询条件用
    public static Timestamp parseTimeStamp00(String t) {
        return parseTimeStamp(t, yyyy_MM_dd_00);
    }

    //查询条件用
    public static Timestamp parseTimeStamp24(String t) {
        return parseTimeStamp(t, yyyy_MM_dd_24);
    }

    //查询条件用
    public static Date parseDateString(String t) {
        return parseDateTime(t, yyyy_MM_dd);
    }

    //查询条件用
    public static Date parseDateStringCN(String t) {
        return parseDateTime(t, yyyyMMddCN);
    }

    public static Date parseDateTimeString(String t) {
        return parseDateTime(t, yyyy_MM_dd_HH_mm_ss);
    }

    //查询条件用
    public static Date parseDateValue(String t) {
        return parseDateTime(t, yyyyMMdd);
    }


    //查询条件用
    public static Date parseTimeStamp0000(String t) {
        if (StringUtils.isBlank(t)) {
            return new Date();
        }
        return parseDateTime(t + " 00:00:00", yyyy_MM_dd_HH_mm_ss);
    }

    public static Date parseDate0000(String t) {
        if (StringUtils.isBlank(t)) {
            return new Date();
        }
        return parseDateTime(t + " 00:00:00", yyyy_MM_dd);
    }

    public static Date parseDate2359(String t) {
        if (StringUtils.isBlank(t)) {
            return new Date();
        }
        return parseDateTime(t + " 23:59:59", yyyy_MM_dd);
    }

    public static Date parseTimeStamp0000(Date d) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(d);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        // 分
        calendar.set(Calendar.MINUTE, 0);
        // 秒
        calendar.set(Calendar.SECOND, 0);
        // 毫秒
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    //查询条件用
    public static Date parseTimeStamp2359(String t) {
        if (StringUtils.isBlank(t)) {
            return new Date();
        }
        return parseDateTime(t + " 23:59:59", yyyy_MM_dd_HH_mm_ss);
    }

    public static Date parseTimeStamp2359(Date d) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(d);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        // 分
        calendar.set(Calendar.MINUTE, 59);
        // 秒
        calendar.set(Calendar.SECOND, 59);
        // 毫秒
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    //=================================日期使用===============================

    public static Date addDays(int days) {
        log.info("72hours question addDays ");
        return addDays(new Date(), days, true);
    }

    public static Date addRealDays(int days) {
        log.info("72hours question addRealDays ");
        return addDays(new Date(), days, false);
    }

    //基础方法
    public static Date addDays(Date date, int days, boolean onlyDay) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_YEAR, days);
        if (onlyDay) {
            calendar.set(Calendar.HOUR, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
        }
        return calendar.getTime();
    }

    public static Date addYears(Date date, int years, boolean onlyYear) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.YEAR, years);
        if (onlyYear) {
            calendar.set(Calendar.HOUR, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
        }
        return calendar.getTime();
    }

    public static Long calculateTimeDifference(Timestamp begin, Timestamp end) {
//        Date beginDate = parseDate(begin);
//        Date endDate = parseDate(end);
        long beginTime = begin.getTime();
        long endTime = end.getTime();
        long minutes = (endTime - beginTime) / 1000;
        return minutes;
    }

    public static Timestamp addHours(int hours) {
        return addHours(new Date(), hours);
    }

    public static Timestamp addHours(Date date, int hours) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.HOUR, hours);
        date = calendar.getTime();
        return new Timestamp(date.getTime());
    }

    public static Timestamp addMinute(int minute) {
        return addMinute(new Date(), minute);
    }

    public static Timestamp addMinute(Date date, int minute) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, minute);
        date = calendar.getTime();
        return new Timestamp(date.getTime());
    }

    public static Timestamp addMonth(Date date, int month) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, month);
        date = calendar.getTime();
        return new Timestamp(date.getTime());
    }


    public static long getDiffDay(String startTime, String endTime) {
        long diffDays = 0;
        Calendar c1 = Calendar.getInstance();
        c1.clear();
        Calendar c2 = Calendar.getInstance();
        c2.clear();
        Date start_Time = parseDateTimeString(startTime);
        Date end_Time = parseDateTimeString(endTime);

        // Set the date for both of the calendar instance
        c1.setTime(start_Time);
        c2.setTime(end_Time);

        // Get the represented date in milliseconds
        long time1 = c1.getTimeInMillis();
        long time2 = c2.getTimeInMillis();

        // Calculate difference in milliseconds
        long diff = time2 - time1;

        // Difference in days
        diffDays = diff / (24 * 60 * 60 * 1000);

        return diffDays;
    }

    public static boolean compareTime(Date startDate, Date endDate) {

        long long1 = startDate.getTime();
        long long2 = endDate.getTime();

        if (long1 > long2) {
            return true;
        }
        return false;
    }

    public static int getDiffMonth(Date startDate, Date endDate) {
        int diffMonth = 0;

        if (null == startDate || null == endDate) {
            return -1;
        }

        Calendar c1 = Calendar.getInstance();
        c1.clear();
        Calendar c2 = Calendar.getInstance();
        c2.clear();
        c1.setTime(startDate);
        c2.setTime(endDate);

        int y1 = c1.get(Calendar.YEAR);
        int y2 = c2.get(Calendar.YEAR);
        int m1 = c1.get(Calendar.MONTH);
        int m2 = c2.get(Calendar.MONTH);

        diffMonth = (y2 - y1) * 12 + m2 - m1;

        return diffMonth;
    }

    public static boolean isBetween(Date d1, Date d2) {
        return isBetween(new Date(), d1, d2);
    }

    public static boolean isBetween(Date d, Date d1, Date d2) {
        boolean result = false;

        if ((d1.before(d) || (d1.equals(d))) && (d2.equals(d) || d2.after(d))) {
            result = true;
        }
        return result;
    }

    public static boolean isOrBetween(Date d, Date d1, Date d2) {
        boolean result = false;

        if ((d1.after(d) || (d1.equals(d))) || (d2.equals(d) || d2.before(d))) {
            result = true;
        }
        return result;
    }

    //基础方法
    private static String formatDateTime(Date date, String formater) {
        SimpleDateFormat sdf = new SimpleDateFormat(formater);
        return sdf.format(null == date ? new Date() : date);
    }

    //基础方法
    private static Date parseDateTime(String ds, String formater) {
        Date date = new Date();
        //注意format的格式要与日期String的格式相匹配
        DateFormat sdf = new SimpleDateFormat(formater);
        try {
            date = sdf.parse(ds);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    //基础方法
    private static Timestamp parseTimeStamp(String ts, String formater) {
        Date date = new Date();
        //注意format的格式要与日期String的格式相匹配
        DateFormat sdf = new SimpleDateFormat(formater);
        try {
            date = sdf.parse(ts);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Timestamp timestamp = new Timestamp(date.getTime());
        return timestamp;
    }

    public static String parseDayByDomainCode(String domainCode) {
        return formatDateString().substring(0, 2) + domainCode.substring(0, 2) + "年" + domainCode.substring(domainCode.length() - 2, domainCode.length()) + "日";
    }

    /**
     * 判断字符串是否是日期格式
     *
     * @param time
     * @return
     */
    public static boolean isDate(String time) {
        try {
            new SimpleDateFormat(yyyy_MM_dd_HH_mm_ss).parse(time);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}
